package opdb

import (
	"database/sql/driver"
	"errors"
	"fmt"
	"io"
	"log"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"time"

	opio "gitee.com/haodreams/godriver/opdb/opio/driver"
)

var dict = map[string]int{
	"ID": opio.VtInt64,
	"GN": opio.VtString,
	"PN": opio.VtString,
	"AV": opio.VtDouble,
	"DS": opio.VtInt32,
	"RT": opio.VtInt32,
	"ED": opio.VtString,
	"TM": opio.VtInt32,
	"KR": opio.VtString,
}

/**
 * @description: 获取类型
 * @param {string} name
 * @return {*}
 */
func GetType(name string) int {
	vt, ok := dict[name]
	if ok && vt > 0 {
		return vt
	}
	return -1
}

// conn ...
type conn struct {
	*opio.IOConnect
	id           int64
	ok           bool
	maxEventSize int
}

func newConn(host string, port int, user, pwd string, timeout, option int, size int) (dc *conn, err error) {
	_ = option //消除警告
	dc = new(conn)
	dc.IOConnect, err = opio.Init(host, port, timeout, user, pwd)
	if err != nil {
		return
	}
	dc.IOConnect.SetCompressModel(opio.ZIP_MODEL_Frame)
	dc.ok = true
	if size < 20 {
		size = 20
	}
	dc.maxEventSize = size
	log.Println("connect to openplant", host, port, "success")
	return
}

// 状态检查
func (m *conn) checkStatus() (err error) {
	if m.ok {
		return nil
	}
	return m.reconnect()
}

func (m *conn) reconnect() (err error) {
	log.Println("openplant reconnect.")
	op, err := m.Copy()
	if err != nil {
		return
	}
	if m.IOConnect != nil {
		m.Close()
	}
	m.IOConnect = op
	m.ok = true
	return
}
func (m *conn) parser(query string, args []driver.Value) string {
	var formattedValues []string
	for _, value := range args {
		indirectValue := reflect.Indirect(reflect.ValueOf(value))
		if indirectValue.IsValid() {
			value = indirectValue.Interface()
			if t, ok := value.(time.Time); ok {
				if t.IsZero() {
					formattedValues = append(formattedValues, fmt.Sprintf("'%v'", "0000-00-00 00:00:00"))
				} else {
					formattedValues = append(formattedValues, fmt.Sprintf("'%v'", t.Format("2006-01-02 15:04:05")))
				}
			} else if b, ok := value.([]byte); ok {
				if str := string(b); isPrintable(str) {
					formattedValues = append(formattedValues, fmt.Sprintf("'%v'", str))
				} else {
					formattedValues = append(formattedValues, "'<binary>'")
				}
			} else if r, ok := value.(driver.Valuer); ok {
				if value, err := r.Value(); err == nil && value != nil {
					formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
				} else {
					formattedValues = append(formattedValues, "NULL")
				}
			} else {
				switch value.(type) {
				case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool:
					formattedValues = append(formattedValues, fmt.Sprintf("%v", value))
				default:
					formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
				}
			}
		} else {
			formattedValues = append(formattedValues, "NULL")
		}
	}

	// differentiate between $n placeholders or else treat like ?
	if numericPlaceHolderRegexp.MatchString(query) {
		for index, value := range formattedValues {
			placeholder := fmt.Sprintf(`\$%d([^\d]|$)`, index+1)
			query = regexp.MustCompile(placeholder).ReplaceAllString(query, value+"$1")
		}
	} else {
		formattedValuesLength := len(formattedValues)
		s := ""
		for index, value := range sqlRegexp.Split(query, -1) {
			s += value
			if index < formattedValuesLength {
				s += formattedValues[index]
			}
		}
		query = s
	}
	return query
}

func (m *conn) getResult(rows *Rows) (result driver.Result, err error) {
	res := new(Result)

	for err = rows.Next(nil); err == nil; err = rows.Next(nil) {
		res.Count++
	}
	if err == io.EOF {
		err = nil
	}
	return res, err
}

func (m *conn) execSQL(query string) (result driver.Result, err error) {
	req := m.makeRequest(opio.ActionExecSQL, query)

	rows, err := m.GetRows(req, true)
	if err != nil {
		return
	}

	return m.getResult(rows)
}

func (m *conn) makeRequest(action string, sql ...string) (req *opio.Request) {
	m.id++
	req = m.NewRequest(nil)
	req.SetID(m.id)
	req.SetService("openplant")
	req.SetAction(action)
	if len(sql) > 0 {
		req.SetSQL(sql[0])
	}
	return
}

// CheckNamedValue 认为所有的列都没有问题 (接口所用)
func (m *conn) CheckNamedValue(nameValue *driver.NamedValue) error {
	return nil
}

// Exec ...
func (m *conn) exec(query string, args []driver.Value) (driver.Result, error) {
	err := m.checkStatus()
	if err != nil {
		return nil, err
	}
	//log.Println(query, len(args))
	str := strings.TrimSpace(query)
	str = strings.ToUpper(str)
	field := strings.Fields(str)
	if len(field) < 2 {
		err := errors.New("SQL command error")
		return nil, err
	}

	switch {
	case strings.HasPrefix(str, "WRITE"):
		switch field[1] {
		case "REALTIME":
			if vals, ok := args[0].([]*Real); ok {
				return m.insertReal("Realtime", vals)
			} else if vals, ok := args[0].([]*Binary); ok {
				return m.insertBinary("Realtime", vals)
			} else if _, ok := args[0].(*Binary); ok {
				return m.insertBinary("Realtime", m.getBinarys(args))
			}
			return m.insert("Realtime", args)
		case "ARCHIVE":
			if vals, ok := args[0].([]*Real); ok {
				return m.insertReal("Archive", vals)
			} else if vals, ok := args[0].([]*Binary); ok {
				return m.insertBinary("Archive", vals)
			} else if _, ok := args[0].(*Binary); ok {
				return m.insertBinary("Archive", m.getBinarys(args))
			}
			return m.insert("Archive", args)
		case "POINT":
			return m.insertPoint("Point", args)
		case "NODE":
			return m.insertNode("Node", args)
		}
	case strings.HasPrefix(str, "REMOVE"):
		switch field[1] {
		case "POINT":
			return m.removePoint("Point", args)
		case "NODE":
			return m.removePoint("Node", args)
		}
	default:
		if len(args) > 0 {
			query = m.parser(query, args)
		}
		return m.execSQL(query)
	}

	return nil, errors.New("不支持的功能")
}

func (m *conn) getBinarys(args []driver.Value) (vals []*Binary) {
	vals = make([]*Binary, len(args))
	i := 0
	for _, v := range args {
		if val, ok := v.(*Binary); ok {
			vals[i] = val
			i++
		}
	}
	vals = vals[:i]
	return
}

// Exec ...
func (m *conn) Exec(query string, args []driver.Value) (driver.Result, error) {
	var result driver.Result
	var err error
	ch := make(chan bool, 1)
	go func() {
		defer func() {
			if er := recover(); er != nil {
				err = errors.New(fmt.Sprint(err))
			}
			ch <- true
		}()
		result, err = m.exec(query, args)
	}()
	select {
	case <-ch:
		close(ch)
		return result, err
	case <-time.After(time.Second * 60):
		m.reconnect()
		return nil, errors.New("exec timeout (60s)")
	}
}

func (m *conn) query(query string) (driver.Rows, error) {
	//now := time.Now()
	//log.Println("begin", query)
	//defer log.Println("end", time.Since(now), query)
	req := m.makeRequest(opio.ActionExecSQL, query)
	rows, err := m.GetRows(req, true)
	if err != nil {
		return nil, err
	}
	return rows, err
}

func (m *conn) GetRows(req *opio.Request, needWrite ...bool) (rows *Rows, err error) {
	defer func() {
		if err != nil {
			m.ok = false
		}
	}()
	if len(needWrite) > 0 && needWrite[0] {
		err = req.WriteAndFlush()
		if err != nil {
			return
		}
	} else {
		req.Flush()
	}
	res, err := req.GetResponse()
	if err != nil {
		return nil, err
	}
	ds := res.GetDataSet()
	rows, err = newRows(ds)
	return
}

// Query 实现接口
func (m *conn) Query(query string, args []driver.Value) (driver.Rows, error) {
	var rows driver.Rows
	var err error
	ch := make(chan bool, 1)
	go func() {
		defer func() {
			if er := recover(); er != nil {
				err = errors.New(fmt.Sprint(err))
			}
			ch <- true
		}()
		rows, err = m.queryData(query, args)
	}()
	select {
	case <-ch:
		close(ch)
		return rows, err
	case <-time.After(time.Second * 120):
		m.reconnect()
		return nil, errors.New("query timeout (120s)")
	}
}

// Query ...
func (m *conn) queryData(query string, args []driver.Value) (driver.Rows, error) {
	err := m.checkStatus()
	if err != nil {
		return nil, err
	}
	//log.Println(query, len(args))
	str := strings.TrimSpace(query)
	str = strings.ToUpper(str)
	field := strings.Fields(str)
	if len(field) < 2 {
		err := errors.New("SQL command error")
		return nil, err
	}
	switch {
	case strings.HasPrefix(str, "EVENT"):
		return m.event(field[1], field[2:], args)
	case strings.HasPrefix(str, "READ"):
		return m.read(field[1], field[2:], args)
	case str == "SELECT TIME":
		return m.query("select strftime('%Y-%m-%d %H:%M:%S','now','localtime') as TM from Root")
	default:
		if len(args) > 0 {
			query = m.parser(query, args)
		}
		return m.query(query)
	}
}

// event 订阅事件
// 自定义 SQL 格式 Event + 空格 + 表名 + 空格
func (m *conn) event(table string, fields []string, args []driver.Value) (driver.Rows, error) {
	for i := range fields {
		args = append(args, strings.TrimSpace(fields[i]))
	}
	if len(args) == 0 {
		return nil, errors.New("no primary key")
	}

	sub, err := m.NewSubscribe(table)
	if err != nil {
		return nil, err
	}

	sub.SetSnapshot(true)
	return newEventRows(sub, args, m.maxEventSize)
}

// readRealtime 读取实时数据
func (m *conn) readRealtime(fields []string, args []driver.Value) (driver.Rows, error) {
	m.id++
	req := m.NewRequest(nil)
	req.SetID(m.id)
	req.SetService("openplant")
	req.SetAction(opio.ActionSelect)
	table := opio.NewTable("Realtime", 0)

	isID := true
	if len(fields) > 0 {
		if strings.HasPrefix(fields[0], "'") {
			isID = false
		} else if len(fields[0]) > 0 {
			c := byte(fields[0][0])
			if c < '0' && c > '9' {
				isID = false
			}
		}
	}

	var namelist []string
	if len(args) > 0 {
		if _, ok := args[0].(string); ok {
			isID = false
		} else if ns, ok := args[0].([]string); ok {
			isID = false
			namelist = ns
		}
	}

	//table.AddColumn("*", opio.VtNull, 0)
	table.AddColumn("ID", opio.VtInt64, 0)
	if !isID {
		table.AddColumn("GN", opio.VtString, 0)
	}
	table.AddColumn("AV", opio.VtInt32, 0)
	table.AddColumn("DS", opio.VtInt32, 0)
	table.AddColumn("TM", opio.VtInt32, 0)
	err := req.SetTable(table)
	if err != nil {
		return nil, err
	}

	if isID {
		ids := make([]int32, len(fields)+len(args))
		idx := 0
		for i := range fields {
			id, err := strconv.Atoi(fields[i])
			if err != nil {
				continue
			}
			ids[idx] = int32(id)
			idx++
		}

		for i := range args {
			switch v := args[i].(type) {
			case int:
				ids[idx] = int32(v)
			case int16:
				ids[idx] = int32(v)
			case int32:
				ids[idx] = int32(v)
			case int64:
				ids[idx] = int32(v)
			case byte:
				ids[idx] = int32(v)
				ids[idx] = int32(v)
			case uint:
				ids[idx] = int32(v)
			case uint16:
				ids[idx] = int32(v)
			case uint32:
				ids[idx] = int32(v)
			case uint64:
				ids[idx] = int32(v)
			default:
				continue
			}
			idx++
		}
		req.SetIndexesInt32("ID", ids)
	} else {
		var names []string
		if len(namelist) > 0 {
			names = make([]string, len(fields)+len(namelist))
		} else {
			names = make([]string, len(fields)+len(args))
		}
		idx := 0
		for i := range fields {
			fields[i] = strings.Trim(fields[i], "'")
			names[idx] = fields[i]
			idx++
		}
		if len(namelist) > 0 {
			for _, name := range namelist {
				names[idx] = name
				idx++
			}
		} else {
			for i := range args {
				if s, ok := args[i].(string); ok {
					names[idx] = s
					idx++
				}
			}
		}
		req.SetIndexesString("GN", names)
	}
	return m.GetRows(req, true)
}

// readIDs 读取ID
func (m *conn) readPoint(fields []string, args []driver.Value) (driver.Rows, error) {
	m.id++
	if len(fields) == 0 {
		fields = append(fields, "ID", "GN", "RT")
	}

	if len(args) == 0 {
		return nil, errors.New("参数错误,缺少关键字")
	}

	req := m.NewRequest(nil)
	req.SetID(m.id)
	req.SetService("openplant")
	req.SetAction(opio.ActionSelect)
	table := opio.NewTable("Point", 0)

	for _, name := range fields {
		vt := GetType(name)
		if vt < 0 {
			continue
		}
		table.AddColumn(name, vt, 0)
	}

	err := req.SetTable(table)
	if err != nil {
		return nil, err
	}

	names, ok := args[0].([]string)
	if ok {

	} else {
		idx := 0
		names = make([]string, len(args))
		for i := range args {
			if s, ok := args[i].(string); ok {
				names[idx] = s
				idx++
			}
		}
		if idx == 0 {
			return nil, errors.New("参数错误,缺少关键字")
		}
		names = names[:idx]
	}

	req.SetIndexesString("GN", names)

	return m.GetRows(req, true)
}

// readIDs 读取ID
func (m *conn) readNode(fields []string, args []driver.Value) (driver.Rows, error) {
	m.id++
	if len(fields) == 0 {
		fields = append(fields, "ID", "GN", "ED")
	}

	if len(args) == 0 {
		return nil, errors.New("参数错误,缺少关键字")
	}

	req := m.NewRequest(nil)
	req.SetID(m.id)
	req.SetService("openplant")
	req.SetAction(opio.ActionSelect)
	table := opio.NewTable("Node", 0)

	for _, name := range fields {
		vt := GetType(name)
		if vt < 0 {
			continue
		}
		table.AddColumn(name, vt, 0)
	}

	err := req.SetTable(table)
	if err != nil {
		return nil, err
	}

	names, ok := args[0].([]string)
	if ok {

	} else {
		idx := 0
		names = make([]string, len(args))
		for i := range args {
			if s, ok := args[i].(string); ok {
				names[idx] = s
				idx++
			}
		}
		if idx == 0 {
			return nil, errors.New("参数错误,缺少关键字")
		}
		names = names[:idx]
	}

	req.SetIndexesString("GN", names)

	return m.GetRows(req, true)
}

// read 批量读取实时数据
func (m *conn) read(table string, fields []string, args []driver.Value) (driver.Rows, error) {
	switch table {
	case "REALTIME":
		return m.readRealtime(fields, args)
	case "POINT": //查询ID
		//基本信息
		return m.readPoint(fields, args)
	case "NODE":
		//基本信息
		return m.readNode(fields, args)
	}
	return nil, errors.New("暂不支持的功能")
}

func (m *conn) insert(tableName string, args []driver.Value) (driver.Result, error) {
	if len(args) == 0 {
		return nil, errors.New("没有数据需要写入")
	}
	req := m.makeRequest(opio.ActionReplace)
	table := opio.NewTable(tableName, 0)
	defer table.Clear()

	isHaveID := true
	if value, ok := args[0].(Valuer); ok {
		if value.GetID() == 0 {
			isHaveID = false
		}
	} else {
		return nil, errors.New("不识别插入的数据格式")
	}

	if isHaveID {
		table.AddColumn("ID", opio.VtInt32, 0)
	} else {
		table.AddColumn("GN", opio.VtString, 0)
	}

	table.AddColumn("AV", opio.VtDouble, 0)
	table.AddColumn("DS", opio.VtInt16, 0)
	table.AddColumn("TM", opio.VtDouble, 0)
	var err error
	for i := range args {
		if value, ok := args[i].(Valuer); ok {
			if isHaveID {
				err = table.SetColumnInt32(0, int32(value.GetID()), 0)
			} else {
				err = table.SetColumnString(0, value.GetName())
			}
			if err != nil {
				return nil, err
			}
			err = table.SetColumnDouble(1, value.GetValue())
			if err != nil {
				return nil, err
			}
			err = table.SetColumnInt16(2, int16(value.GetStatus()), 0)
			if err != nil {
				return nil, err
			}
			//table.SetColumnInt64(3, value.GetUnixTime(), 0)
			err = table.SetColumnDouble(3, value.GetTime())
			if err != nil {
				return nil, err
			}
			table.BindRow()
		}
	}

	err = req.SetTable(table)
	if err != nil {
		return nil, err
	}
	err = req.Write()
	if err != nil {
		m.ok = false
		return nil, err
	}
	err = req.WriteContent(table)
	if err != nil {
		m.ok = false
		return nil, err
	}

	rows, err := m.GetRows(req)
	if err != nil {
		return nil, err
	}

	return m.getResult(rows)
}

func (m *conn) insertReal(tableName string, args []*Real) (driver.Result, error) {
	if len(args) == 0 {
		return nil, errors.New("没有数据需要写入")
	}
	req := m.makeRequest(opio.ActionReplace)
	table := opio.NewTable(tableName, 0)
	defer table.Clear()

	isHaveID := true
	if args[0].ID == 0 {
		isHaveID = false
	}

	if isHaveID {
		table.AddColumn("ID", opio.VtInt32, 0)
	} else {
		table.AddColumn("GN", opio.VtString, 0)
	}

	table.AddColumn("AV", opio.VtDouble, 0)
	table.AddColumn("DS", opio.VtInt16, 0)
	table.AddColumn("TM", opio.VtDouble, 0)
	var err error
	for i := range args {
		value := args[i]
		if isHaveID {
			err = table.SetColumnInt32(0, int32(value.ID), 0)
		} else {
			err = table.SetColumnString(0, value.Name)
		}
		if err != nil {
			return nil, err
		}
		err = table.SetColumnDouble(1, value.Value)
		if err != nil {
			return nil, err
		}
		err = table.SetColumnInt16(2, int16(value.Status), 0)
		if err != nil {
			return nil, err
		}
		//table.SetColumnInt64(3, value.GetUnixTime(), 0)
		err = table.SetColumnDouble(3, float64(value.Time))
		if err != nil {
			return nil, err
		}
		table.BindRow()
	}

	err = req.SetTable(table)
	if err != nil {
		return nil, err
	}
	err = req.Write()
	if err != nil {
		m.ok = false
		return nil, err
	}
	err = req.WriteContent(table)
	if err != nil {
		m.ok = false
		return nil, err
	}

	rows, err := m.GetRows(req)
	if err != nil {
		return nil, err
	}

	return m.getResult(rows)
}

func (m *conn) insertBinary(tableName string, args []*Binary) (driver.Result, error) {
	if len(args) == 0 {
		return nil, errors.New("没有数据需要写入")
	}
	req := m.makeRequest(opio.ActionReplace)
	table := opio.NewTable(tableName, 0)
	defer table.Clear()

	isHaveID := true
	if args[0].ID == 0 {
		isHaveID = false
	}

	if isHaveID {
		table.AddColumn("ID", opio.VtInt32, 0)
	} else {
		table.AddColumn("GN", opio.VtString, 0)
	}

	table.AddColumn("AV", opio.VtBinary, 0)
	table.AddColumn("DS", opio.VtInt16, 0)
	table.AddColumn("TM", opio.VtDouble, 0)
	var err error
	for i := range args {
		value := args[i]
		if isHaveID {
			err = table.SetColumnInt32(0, int32(value.ID), 0)
		} else {
			err = table.SetColumnString(0, value.Name)
		}
		if err != nil {
			return nil, err
		}
		err = table.SetColumnBinary(1, value.Value)
		if err != nil {
			return nil, err
		}
		err = table.SetColumnInt16(2, int16(value.Status), 0)
		if err != nil {
			return nil, err
		}
		//table.SetColumnInt64(3, value.GetUnixTime(), 0)
		err = table.SetColumnDouble(3, float64(value.Time))
		if err != nil {
			return nil, err
		}
		table.BindRow()
	}

	err = req.SetTable(table)
	if err != nil {
		return nil, err
	}
	err = req.Write()
	if err != nil {
		m.ok = false
		return nil, err
	}
	err = req.WriteContent(table)
	if err != nil {
		m.ok = false
		return nil, err
	}

	rows, err := m.GetRows(req)
	if err != nil {
		return nil, err
	}

	return m.getResult(rows)
}

func (m *conn) insertPoint(tableName string, args []driver.Value) (driver.Result, error) {
	if len(args) == 0 {
		return nil, errors.New("没有数据需要写入")
	}
	req := m.makeRequest(opio.ActionReplace)
	table := opio.NewTable(tableName, 0)
	defer table.Clear()

	isHaveID := false
	if value, ok := args[0].(*Point); ok {
		if value.ID > 0 {
			isHaveID = true
		}
	} else {
		return nil, errors.New("不识别插入的数据格式")
	}

	if isHaveID {
		table.AddColumn("ID", opio.VtInt32, 0)
	} else {
		table.AddColumn("GN", opio.VtString, 0)
	}

	table.AddColumn("RT", opio.VtInt32, 0)
	table.AddColumn("ED", opio.VtString, 0)
	table.AddColumn("KR", opio.VtString, 0)
	table.AddColumn("FM", opio.VtInt32, 0)
	var err error
	for i := range args {
		if value, ok := args[i].(*Point); ok {
			if isHaveID {
				err = table.SetColumnInt32(0, int32(value.ID), 0)
			} else {
				err = table.SetColumnString(0, value.Name)
			}
			if err != nil {
				return nil, err
			}
			err = table.SetColumnInt32(1, int32(value.Type), 0)
			if err != nil {
				return nil, err
			}
			err = table.SetColumnString(2, value.Desc)
			if err != nil {
				return nil, err
			}
			err = table.SetColumnString(3, value.KR)
			if err != nil {
				return nil, err
			}
			err = table.SetColumnInt32(4, int32(value.FM), 0)
			if err != nil {
				return nil, err
			}
			table.BindRow()
		}
	}

	err = req.SetTable(table)
	if err != nil {
		return nil, err
	}
	err = req.Write()
	if err != nil {
		m.ok = false
		return nil, err
	}
	err = req.WriteContent(table)
	if err != nil {
		m.ok = false
		return nil, err
	}

	rows, err := m.GetRows(req)
	if err != nil {
		return nil, err
	}

	return m.getResult(rows)
}

func (m *conn) insertNode(tableName string, args []driver.Value) (driver.Result, error) {
	if len(args) == 0 {
		return nil, errors.New("没有数据需要写入")
	}
	req := m.makeRequest(opio.ActionReplace)
	table := opio.NewTable(tableName, 0)
	defer table.Clear()

	table.AddColumn("GN", opio.VtString, 0)
	table.AddColumn("ED", opio.VtString, 0)
	var err error
	for i := range args {
		if value, ok := args[i].(*Node); ok {
			err = table.SetColumnString(0, value.Name)
			if err != nil {
				return nil, err
			}

			err = table.SetColumnString(1, value.Desc)
			if err != nil {
				return nil, err
			}

			table.BindRow()
		}
	}

	err = req.SetTable(table)
	if err != nil {
		return nil, err
	}
	err = req.Write()
	if err != nil {
		m.ok = false
		return nil, err
	}
	err = req.WriteContent(table)
	if err != nil {
		m.ok = false
		return nil, err
	}

	rows, err := m.GetRows(req)
	if err != nil {
		return nil, err
	}

	return m.getResult(rows)
}

func (m *conn) removePoint(tableName string, args []driver.Value) (driver.Result, error) {
	if len(args) == 0 {
		return nil, errors.New("没有数据需要写入")
	}
	req := m.makeRequest(opio.ActionDelete)
	table := opio.NewTable(tableName, 0)
	defer table.Clear()

	names, ok := args[0].([]string)
	if !ok {
		return nil, errors.New("不识别插入的数据格式")
	}
	table.AddColumn("GN", opio.VtString, 0)
	var err error
	for i := range names {
		err = table.SetColumnString(0, names[i])
		if err != nil {
			return nil, err
		}
		table.BindRow()
	}

	err = req.SetTable(table)
	if err != nil {
		return nil, err
	}
	err = req.Write()
	if err != nil {
		m.ok = false
		return nil, err
	}
	err = req.WriteContent(table)
	if err != nil {
		m.ok = false
		return nil, err
	}

	rows, err := m.GetRows(req)
	if err != nil {
		return nil, err
	}

	return m.getResult(rows)
}

// Begin ...
func (m *conn) Begin() (driver.Tx, error) {
	return &Tx{}, nil
}

// Prepare ...
func (m *conn) Prepare(query string) (driver.Stmt, error) {
	log.Println(query)
	return nil, errors.New("unsupport prepare function")
}

// Close 释放资源
func (m *conn) Close() error {
	if m.IOConnect != nil {
		err := m.IOConnect.Close()
		m.IOConnect = nil
		log.Println("close openplant connect.")
		return err
	}
	return nil
}
